import json
import logging
import urllib.parse

import requests
from requests.structures import CaseInsensitiveDict

from .mmodel import HttpResponse


def do_request(request_name, url, method, data=None, params=None, headers: CaseInsensitiveDict[str] = None,
               cookies=None,
               timeout=10000) -> HttpResponse:
    response = None
    try:
        response = requests.request(url=url, method=method, cookies=cookies, data=data, timeout=timeout, params=params,
                                    headers=headers)

        if response.status_code == 200:
            content_type = response.headers.get("Content-type")
            if content_type is not None and content_type != "" and content_type.lower().__contains__("json"):
                return HttpResponse(request_name, url=url, method=method, req_data=data, data=response.json(),
                                    status=200,
                                    headers=response.headers,
                                    content=response.content,
                                    stat=True)

            return HttpResponse(request_name, url=url, method=method, content=response.content,
                                status=response.status_code,
                                req_data=data,
                                headers=response.headers,
                                stat=True)

        else:
            return HttpResponse(request_name, url=url, method=method, content=response.content,
                                status=response.status_code,
                                req_data=data,
                                headers=response.headers,
                                stat=False)
    except Exception as err:
        logging.exception(f"执行{request_name} >> http get {url} 异常:\n{err}")
        return HttpResponse(request_name, url=url, method=method, stat=False)
    finally:
        if response is not None:
            response.close()


def do_get(request_name, url, data=None, params=None, headers=None, cookies=None, timeout=10000) -> HttpResponse:
    return do_request(request_name, url=url, method='GET', data=data, params=params, headers=headers, cookies=cookies,
                      timeout=timeout)


def do_post(request_name, url, data=None, params=None, headers: CaseInsensitiveDict[str] = None, cookies=None,
            timeout=10000) -> HttpResponse:
    return do_request(url=url, method='POST', data=data, params=params, headers=headers, cookies=cookies,
                      timeout=timeout)


def do_post_json(request_name, url, data=None, params=None, headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(),
                 cookies=None,
                 timeout=10000) -> HttpResponse:
    headers.setdefault("Content-type", "application/json;charset=utf-8")
    req_data = data_convert(data, lambda x: json.dumps(x))

    return do_request(url=url, method='POST', data=req_data, params=params, headers=headers, cookies=cookies,
                      timeout=timeout)


def do_post_form(request_name, url, data=None, params=None, headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(),
                 cookies=None,
                 timeout=10000) -> HttpResponse:
    headers.setdefault("Content-type", "application/x-www-form-urlencoded;charset=utf-8")
    req_data = data_convert(data, lambda x: urllib.parse.urlencode(x, encoding="utf-8"))

    return do_request(url=url, method='POST', data=req_data, params=params, headers=headers, cookies=cookies,
                      timeout=timeout)


def data_convert(data, func):
    if data is None:
        return data
    data_type = type(data)
    if data_type is None or data_type is str or data_type is bytes or data is bytearray:
        return data
    else:
        return func(data)
